/*
 *      Matrix.java
 *		Code for initialising an empty matrix with labels in 0 row and column and printing to console.
 *
 */

/**
 * Represents a square matrix of integers
 * @author ofek
 */
public class Matrix
{
        final int NOT_IN_USE = -1; //represents an element of the matrix which is no longer used, e.g when rows are merged, then one row will not be in use anymore, and its elements will be marked with this flag   
        private Boolean _debug = main.debug;
        protected int _size; //how many vertices in the matrix, the actual dimension of the array is one more bcs count starts with 1 and not 0	
        /**
         * Holds the actual matrix elements
         */
        public int[][] element; 

        /**
         * Constructs a zero square matrix of size s.
         * @param s the size of the matrix
         */
        public Matrix(int s)
        {
                if(_debug) System.out.println("New matrix");
                
                _size = s;
                element = new int[_size][_size];

        }

        /**
         * A deep copy constructor
         * @param m the matrix to clone
         */
        public Matrix(Matrix m)
        {
                if(_debug) System.out.println("New matrix from another matrix");
                int i,j;

                _size = m._size;
                element = new int[_size][_size];

                for (i=0; i < _size; i++)
                    for (j=0 ; j< _size;j++)
                        element[i][j] = m.element[i][j];

        }

        /**
         * Merge a pair of rows and columns, e.g if we get 2 and 4, it will merge rows 2 and 4 and also columns 2 and 4 (the merge is done by summing)
         * @param index1 an index of a row/column to be merged
         * @param index2 another index of a row/column to be merged
         */
        public void mergeRowsColsBySumming(int index1, int index2)
        {
            int smaller_index, larger_index;
            
            if (index1 < index2) { smaller_index = index1; larger_index = index2; }
            else if (index2 < index1) { smaller_index = index2; larger_index = index1; }
            else { throw new IllegalArgumentException("Indices of rows/columns to merge must be different"); }
            
            //Merge rows
            for (int i=0;i<this._size;i++)
            {
                if (this.element[smaller_index][i] == NOT_IN_USE)
                {
                    //This should only happen if the whole column is not in use anymore
                    //The following comment can be used to assert that this is true
                    /*
                    for (int j=0;j<this.size;j++)
                    {
                        assert (this.matrix[j][i] == NOT_IN_USE);
                    }
                    */
                }
                else
                {
                    this.element[smaller_index][i] += this.element[larger_index][i];
                    this.element[larger_index][i] = NOT_IN_USE;
                }
            }
            
            //Merge columns
            for (int i=0;i<this._size;i++)
            {
                if (this.element[i][smaller_index] == NOT_IN_USE)
                {
                    //This should only happen if the whole row is not in use anymore
                    //The following comment can be used to assert that this is true
                    /*
                    for (int j=0;j<this.size;j++)
                    {
                        assert (this.matrix[i][j] == NOT_IN_USE);
                    }
                    */
                }
                else
                {
                    this.element[i][smaller_index] += this.element[i][larger_index];
                    this.element[i][larger_index] = NOT_IN_USE;
                }
            }
        }
        
        /**
         * Prints the matrix to standard output
         */
        public void print()
        {
                int i,j;
                for (i = 0; i < _size; i++)
                {
                        for (j = 0; j < _size; j++)
                                System.out.print(element[i][j] + " ");

                        System.out.println();
                }
        }
}
